#include "LiteMiddle.h"

#define QUEUELENGTH_ATCMD_SEND  64  //Miaozi:AT发送命令队列深度
#define BUFSIZE_ATCMD_PARAS 1024    //Miaozi:AT发送需要的参数
#define BUFSIZE_ATCMD_RECV  2048    //Miaozi:AT接收缓存区

LITEAT_T  g_tAtHandler;                                                  //  AT运行时指针
static  QueueHandle_t          s_xQueueAtCmdId;                          //  待发送的AT命令队列  

//////////////AT发送
static  LITE_ATSEND_T          s_tAtSend;                                                  //  AtSend操作句柄
static  u8                     s_ucaBufAtCmdParas[BUFSIZE_ATCMD_PARAS];                    //  AtSend存储缓存区：AT发送需要的参数
static  BUFFER_T               BufAtCmdParas ={s_ucaBufAtCmdParas,BUFSIZE_ATCMD_PARAS,0};  //  AtSend逻辑缓存区：AT发送需要的参数
//////////////AT发送
//////////////AT接收
static  LITE_ATRECV_T          s_tAtRecv;                                            //  AtRecv操作句柄
static  MessageBufferHandle_t  s_xMsgBufAtRecv;                                      //  消息缓冲区：ATRECV
static  u8                     s_ucaBufRecvAtCmd[BUFSIZE_ATCMD_RECV];                //  AtRecv存储缓存区
static  BUFFER_T               BufAtRecv ={s_ucaBufRecvAtCmd,BUFSIZE_ATCMD_RECV,0};  //  AtRecv逻辑缓存区
//////////////AT接收

// AT模块初始化
void LITE_AT_Init(void)
{
  s_xQueueAtCmdId            =  xQueueCreate(QUEUELENGTH_ATCMD_SEND, sizeof(AT_ID_E));    //  队列存储初始化
  g_tAtHandler.xQueueAtCmd   =  s_xQueueAtCmdId;
  g_tAtHandler.tpUart        =  &ESP32_UART;        //  At串口等同于ESP32串口
  
  g_tAtHandler.eRecvState        = ATRECV_STATE_INIT;    //  空闲状态   
  g_tAtHandler.eSendState      = ATSEND_STATE_INIT;    //  空闲状态

  ////////////////AtSend句柄初始化
  s_tAtSend.FsmState        = ATSEND_STEP_INIT;         //Miaozi：Send状态机
  s_tAtSend.tpxMutexAtSend  = g_xMutexEsp32Tx;          //Miaozi：Send信号量
  s_tAtSend.pAtCmdParasBuf  = &BufAtCmdParas;           //Miaozi：AT发送需要的参数
  s_tAtSend.pAtCmdSendBuf   = g_tAtHandler.tpUart->tpTxBuf;    //Miaozi：命令存储缓存区
  g_tAtHandler.tpAtSendHandler  = &s_tAtSend;           //Miaozi：指向AT发送结构体
  ////////////////AtSend句柄初始化

  ////////////////AtRecv句柄初始化
  s_xMsgBufAtRecv               = xMessageBufferCreate(g_tAtHandler.tpUart->tpRxBuf->size*2); //  消息队列尺寸为接收缓冲区尺寸两倍
  s_tAtRecv.tpxMsgBufAtRecv = s_xMsgBufAtRecv;
  s_tAtRecv.pAtCmdRecvBuf   = &BufAtRecv;               //Miaozi：命令存储缓存区
  g_tAtHandler.tpAtRecvHandler  = &s_tAtRecv;           //Miaozi：指向AT接收结构体
  ////////////////AtRecv句柄初始化
  
  //step 断言保护，为假触发断言
  configASSERT(s_tAtRecv.tpxMsgBufAtRecv);    
  configASSERT(s_tAtSend.tpxMutexAtSend);
  return;
}

/*
******************************************************************************************************
***
* 函 数 名:   LITE_AT_EnQueueCmd
* 功能说明:   AT命令压队
* 形    参:
* 返 回 值:   无
******************************************************************************************************
***
*/
void LITE_AT_EnQueueCmd(AT_ID_E index)
{
  xQueueSend(g_tAtHandler.xQueueAtCmd,&index,portMAX_DELAY);
  return;
}

///////////////////////////////////////////ATRECV///////////////////////////////////////////
/*
*********************************************************************************************************
* 函 数 名:   LITE_ATRECV_SetCmdId
* 功能说明:   设置当前等待回复的AT
* 形    参:   
* 返 回 值:   无
*********************************************************************************************************
*/
void LITE_ATRECV_SetCmdId(AT_ID_E index)
{
  g_tAtHandler.tpAtRecvHandler->pAtCmd  = g_AtCmds+index;   //Miaozi:得到静态命令
  g_tAtHandler.tpAtRecvHandler->RecvId  = index;              //Miaozo:配置ID
  return;
}


/*
*********************************************************************************************************
* 函 数 名:   LITE_ATRECV_GetCmdId
* 功能说明:   得到当前等待回复的AT
* 形    参:   
* 返 回 值:   无
*********************************************************************************************************
*/
u8 LITE_ATRECV_GetCmdId(void)
{
  return g_tAtHandler.tpAtRecvHandler->RecvId;
}
/*
*********************************************************************************************************
* 函 数 名:   LITE_ATRECV_ClrCmdId
* 功能说明:   清除当前等待回复的AT
* 形    参:   
* 返 回 值:   无
*********************************************************************************************************
*/
void LITE_ATRECV_ClrCmdId(void)
{
  g_tAtHandler.tpAtRecvHandler->RecvId=NONE;
  return ;
}
///////////////////////////////////////////ATRECV///////////////////////////////////////////

///////////////////////////////////////////ATSEND///////////////////////////////////////////
//  设置ATSEND当前发送命令
void  LITE_ATSEND_SetCmdid(AT_ID_E AtCmdId)
{
  g_tAtHandler.tpAtSendHandler->SendId  = AtCmdId;
  return;
}

//  设置发送状态机阶段
void LITE_ATSEND_SetState(ATSEND_STEP_E Index)
{
  g_tAtHandler.tpAtSendHandler->FsmState=Index;
  return  ;
}

//  得到发送命令
static LITEAT_CMD_T  *LITE_ATSEND_GetProcessCmd(void)
{
  return  g_AtCmds+g_tAtHandler.tpAtSendHandler->SendId;
}
//  得到发送缓存区
static BUFFER_T  *LITE_ATSEND_GetProcessBuf(void)
{
  return  g_tAtHandler.tpAtSendHandler->pAtCmdSendBuf;
}
//  得到参数缓存区
static BUFFER_T  *LITE_ATSEND_GetParasBuf(void)
{
  return  g_tAtHandler.tpAtSendHandler->pAtCmdParasBuf;
}

//  AT的Send执行状态机
u8 LITE_ATSEND_Process(void)
{ 
  LITE_ATSEND_T   *pAtSendHandler    = g_tAtHandler.tpAtSendHandler;                //Miaozi:发送句柄
  LITEAT_CMD_T  *pAtSendCmd;      //Miaozi:命令句柄
  BUFFER_T      *pAtSendBuf;      //Miaozi:缓存区句柄-发送缓存区
  BUFFER_T      *pAtParas;        //Miaozi:缓存区句柄-命令参数
  u8  ret;
  switch (pAtSendHandler->FsmState)
  {
    ///////////////////////////////Miaozi:发送阶段初始化
    case ATSEND_STEP_INIT:
      if(pAtSendHandler->SendId < AT)     //Miaozi:未知指令
      {
        ret=AT_RET_ERROR;             //Miaozi:产生错误
        break;                    //Miaozi:截断执行
      }
      LITE_ATSEND_SetState(ATSEND_STEP_SENDING);      //Miaozi：跳转至发送状态
      break;
   ///////////////////////////////Miaozi:发送中
    case  ATSEND_STEP_SENDING:
      pAtSendCmd = LITE_ATSEND_GetProcessCmd();                   //Miaozi：取到命令指针
      pAtSendBuf = LITE_ATSEND_GetProcessBuf();                   //Miaozi：取到缓存区指针
      pAtParas   = LITE_ATSEND_GetParasBuf();                     //Miaozi：取到参数缓存区指针
      BUF_DelData(pAtSendBuf);                              //Miaozi：清空发送缓存
      if(pAtSendCmd->on_send==NULL)                         //Miaozi：存在发送前钩子
        ret=AT_RET_OK;
      else
        ret=pAtSendCmd->on_send(pAtSendBuf,pAtSendCmd->pAtCmdStr,pAtParas->data); //Miaozi:发送前处理
  
      if(ret==AT_RET_OK)                                          //Miaozi：处理成功
      {
        BSP_ESP32_Send(pAtSendBuf->data ,pAtSendBuf->length); //Miaozi：透传给模块
        ret=AT_RET_DELAY; //Miaozi：请求外部延时
      }
      else
      {
        ret=AT_RET_ERROR; //Miaozi:产生错误
      }
      break;
    ///////////////////////////////Miaozi:发送完成  检测
    case ATSEND_STEP_FINISHCHECK:
      if(IS_FLAG_SET(ESP32_UART.state,UART_TX_DONE))  //Miaozi：检测串口是否完成发送
      {
        LITE_ATSEND_SetState(ATSEND_STEP_INIT);          //Miaozi：跳转至初始状态
        LITE_ATRECV_SetCmdId(pAtSendHandler->SendId);  //Miaozi：设置等待恢复的AT指令
        ret=AT_RET_OK;      
      }
      else
        ret=AT_RET_ERROR;                                 //Miaozi:产生错误
      break;
  }

  ///////////////////////////////保护
  if(ret==AT_RET_ERROR)
  {
    LITE_ATSEND_SetState(ATSEND_STEP_INIT);       //Miaozi：跳转至初始状态
  }
  
  return ret;
}
///////////////////////////////////////////ATSEND///////////////////////////////////////////

/////////////////////////发送给ESP32中断函数
void LITE_AT_TxHandler(UART_HandleTypeDef *huart)
{
  //Miaozi：保护
  if(huart != g_tAtHandler.tpUart->tpUart)  return;

  SET_FLAG(g_tAtHandler.tpUart->state, UART_TX_DONE);  //Miaozi：置位发送完成

  BaseType_t xHigherPriorityTaskWoken = pdFALSE;
  xSemaphoreGiveFromISR(g_tAtHandler.tpAtSendHandler->tpxMutexAtSend,&xHigherPriorityTaskWoken);  //Miaozi：释放信号量——线程安全  
  vTaskNotifyGiveFromISR(xTaskHandle_AtSend,&xHigherPriorityTaskWoken);                           //Miaozi:唤醒发送任务
  portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
  return;
}

/////////////////////////接收ESP32完成中断函数
void LITE_AT_RxHandler(UART_HandleTypeDef *huart,u16 Size)
{
  //Miaozi：保护
  if(huart != g_tAtHandler.tpUart->tpUart)  return;

  // step1：标记一次接收
  SET_FLAG(g_tAtHandler.tpUart->state,UART_RX_DONE); //  置位接收完成
  g_tAtHandler.tpUart->tpRxBuf->length  = Size;
  // step2：继续开启下一次接收
  HAL_UARTEx_ReceiveToIdle_DMA(g_tAtHandler.tpUart->tpUart,g_tAtHandler.tpUart->tpRxBuf->data,g_tAtHandler.tpUart->tpRxBuf->size);
  __HAL_DMA_DISABLE_IT(g_tAtHandler.tpUart->tpDmaRx, DMA_IT_HT);    //  关闭DMA半中断
  // step3：放入消息缓存
  BaseType_t xHigherPriorityTaskWoken = pdFALSE;
  xMessageBufferSendFromISR(g_tAtHandler.tpAtRecvHandler->tpxMsgBufAtRecv,g_tAtHandler.tpUart->tpRxBuf->data,g_tAtHandler.tpUart->tpRxBuf->length,&xHigherPriorityTaskWoken);

  return;
}

/***************************** LiteBsp by Miaozi (END OF FILE) *********************************/

